package avicit.bdp.dgs.metadata.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.service.dto.BdpTableDTO;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.common.utils.EntityUtils;
import avicit.bdp.core.enums.TableTypeEnum;
import avicit.bdp.dgs.metadata.dao.MetadataBaseVersionDetailDao;
import avicit.bdp.dgs.metadata.dto.MetadataBaseVersionDTO;
import avicit.bdp.dgs.metadata.dto.MetadataBaseVersionDetailDTO;
import avicit.bdp.dgs.metadata.vo.MetadataBaseChangeVo;
import avicit.bdp.dgs.metadata.vo.MetadataTableVo;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.exception.DaoException;
import avicit.platform6.modules.system.syslog.service.SysLogUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class MetadataBaseVersionDetailService
    extends BaseService<MetadataBaseVersionDetailDao, MetadataBaseVersionDetailDTO> {

  @Resource private MetadataBaseVersionService metadataBaseVersionService;
  @Resource private MetadataTableService metadataTableService;

  /**
   * 元数据第一次采集，自动为该数据源创建一个基线版本
   *
   * @param dto 保存对象
   * @return String
   */
  @Transactional
  public String save(MetadataBaseVersionDetailDTO dto) {
    try {
      dto.setId(ComUtil.getId());
      this.insertWithoutVersion(dto);
      // 记录日志
      SysLogUtil.log4Insert(dto);
      return dto.getId();
    } catch (Exception e) {
      throw new DaoException(e.getMessage(), e);
    }
  }

  @Transactional
  public void batchSave(List<MetadataBaseVersionDetailDTO> list) {
    if (CollectionUtils.isNotEmpty(list)) {
      int start = 0;
      int totalSize = list.size();
      while (true) {
        // 以100条记录为单位分批存储
        int end = Math.min(start + 100, totalSize);
        this.mapper.batchSave(list.subList(start, end));
        if (end >= totalSize) {
          break;
        }
        start = end;
      }
    }
  }

  @Transactional
  public void batchUpdate(List<MetadataBaseVersionDetailDTO> list) {
    if (CollectionUtils.isNotEmpty(list)) {
      int start = 0;
      int totalSize = list.size();
      while (true) {
        // 以100条记录为单位分批存储
        int end = Math.min(start + 100, totalSize);
        this.mapper.batchUpdate(list.subList(start, end));
        if (end >= totalSize) {
          break;
        }
        start = end;
      }
    }
  }

  public Integer getBaseVersionUpdateNum(String dataSourceId) {
    return this.mapper.getBaseVersionUpdateNum(dataSourceId);
  }

  public Page<MetadataTableVo> getUpdateDetailPageList(
      String dataSourceId, String keyWords, Integer type, Integer pageNo, Integer pageSize) {
    PageHelper.startPage(pageNo, pageSize);
    return this.mapper.getUpdateDetailPageList(dataSourceId, keyWords, type);
  }

  public boolean batchUpdateVersion(String dataSourceId, List<String> ids) {
    if (CollectionUtils.isNotEmpty(ids)) {
      // 查询基线版本
      MetadataBaseVersionDTO metadataBaseVersion =
          metadataBaseVersionService.getOneByDatasourceId(dataSourceId);
      Objects.requireNonNull(metadataBaseVersion, "基线版本不存在");

      List<BdpTableDTO> tableList =
          metadataTableService.queryTableList(
              dataSourceId, TableTypeEnum.TABLE_METADATA.getCode(), false, ids);

      List<MetadataBaseVersionDetailDTO> baseVersionDetailList =
          this.mapper.getBaseVersionList(ids);

      Map<String, MetadataBaseVersionDetailDTO> map =
          baseVersionDetailList.stream()
              .collect(Collectors.toMap(MetadataBaseVersionDetailDTO::getMetadataId, t -> t));

      // 基线版本存在更新版本,基线版本不存在新建基线
      List<MetadataBaseVersionDetailDTO> addList = new ArrayList<>();
      List<MetadataBaseVersionDetailDTO> updateList = new ArrayList<>();

      for (BdpTableDTO metadata : tableList) {
        if (map.containsKey(metadata.getId())) {
          MetadataBaseVersionDetailDTO item = map.get(metadata.getId());
          item.setMetadataVersion(metadata.getTableVersion());
          updateList.add(item);
        } else {
          MetadataBaseVersionDetailDTO versionDetailDTO = new MetadataBaseVersionDetailDTO();
          versionDetailDTO.setId(ComUtil.getId());
          versionDetailDTO.setMetadataBaseVersionId(metadataBaseVersion.getId());
          versionDetailDTO.setDatasourceId(metadata.getDataSourceId());
          versionDetailDTO.setMetadataId(metadata.getId());
          versionDetailDTO.setMetadataVersion(metadata.getTableVersion());
          EntityUtils.setCreateAndUpdateInfo(versionDetailDTO);
          addList.add(versionDetailDTO);
        }
      }

      if (CollectionUtils.isNotEmpty(addList)) {
        this.batchSave(addList);
      }
      if (CollectionUtils.isNotEmpty(updateList)) {
        this.batchUpdate(updateList);
      }
    }
    return true;
  }

  public Boolean changeBaseVersion(MetadataBaseChangeVo updateDto) {
    CheckParaUtils.checkStringValidity(updateDto.getMetadataId(), logger, "元数据ID不能为空");
    CheckParaUtils.checkStringValidity(updateDto.getMetadataVersion(), logger, "元数据版本不能为空");

    BdpTableDTO metadata = metadataTableService.selectByPrimaryKey(updateDto.getMetadataId());
    CheckParaUtils.checkObjectValidity(metadata, logger, "元数据不存在");

    MetadataBaseVersionDTO metadataBaseVersion =
        metadataBaseVersionService.getOneByDatasourceId(metadata.getDataSourceId());
    CheckParaUtils.checkObjectValidity(metadataBaseVersion, logger, "数据源基线版本不存在");

    MetadataBaseVersionDetailDTO query = new MetadataBaseVersionDetailDTO();
    query.setDatasourceId(metadata.getDataSourceId());
    query.setMetadataId(updateDto.getMetadataId());
    query.setMetadataBaseVersionId(metadataBaseVersion.getId());

    MetadataBaseVersionDetailDTO metadataBaseVersionDetail = this.selectOne(query);
    if (metadataBaseVersionDetail != null) {
      metadataBaseVersionDetail.setMetadataVersion(updateDto.getMetadataVersion());
      return this.updateByPrimaryKey(metadataBaseVersionDetail) > 0;
    } else {
      metadataBaseVersionDetail = new MetadataBaseVersionDetailDTO();
      metadataBaseVersionDetail.setMetadataVersion(updateDto.getMetadataVersion());
      metadataBaseVersionDetail.setDatasourceId(metadata.getDataSourceId());
      metadataBaseVersionDetail.setMetadataId(updateDto.getMetadataId());
      metadataBaseVersionDetail.setMetadataBaseVersionId(metadataBaseVersion.getId());
      return StringUtils.isNotEmpty(this.save(metadataBaseVersionDetail));
    }
  }

  public void batchDeleteByBaseVersionIdAndMetadataIds(
      String metadataBaseVersionId, List<String> metaDataIdList) {
    this.mapper.batchDeleteByBaseVersionIdAndMetadataIds(metadataBaseVersionId, metaDataIdList);
  }

  public List<String> selectMetadataIdList(String datasourceId) {
    return this.mapper.selectMetadataIdList(datasourceId);
  }
}
